package com.wildish.core.controller;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;

/**
 * controller服务基类
 * 
 * @author Keith 2013-03-15 17:06:33
 */
public class WebSupport {
	private static String APP_PATH = "/app";
	private ThreadLocal<HttpServletRequest> request = new ThreadLocal<HttpServletRequest>();
	private ThreadLocal<HttpServletResponse> response = new ThreadLocal<HttpServletResponse>();

	/**
	 * 返回spring用forward地址.
	 * 
	 * @param path
	 * @return
	 */
	public String forward(String path) {
		Assert.notNull(path, "forward path must be not null");
		path = (path.startsWith("/") ? "" : "/") + path;
		return "forward:" + WebSupport.APP_PATH + path;
	}

	/**
	 * 返回spring用redirect地址.
	 * 
	 * @param path
	 * @return
	 */
	public String redirect(String path) {
		Assert.notNull(path, "redirect path must be not null");
		path = path.startsWith("/") ? path : "/" + path;
		return "redirect:" + path;
	}

	/**
	 * 向session中存放对象
	 */
	public void setSession(String key, Object value) {
		HttpServletRequest request = this.getRequest().get();
		HttpSession session = request.getSession(true);
		session.setAttribute(key, value);
	}

	/**
	 * 从session中取对象
	 */
	public Object getSession(String key) {
		HttpServletRequest request = this.getRequest().get();
		HttpSession session = request.getSession(true);
		return session.getAttribute(key);
	}

	/**
	 * 直接输出纯字符串.
	 */
	public void writeResponse(String text) {
		HttpServletResponse response = this.getResponse().get();
		response.setContentType("text/plain;charset=UTF-8");
		try
		{
			response.getWriter().write(text);
			response.getWriter().flush();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 直接输出xml.
	 */
	public void writeXMLResponse(String text) {
		HttpServletResponse response = this.getResponse().get();
		response.setContentType("application/xml;charset=UTF-8");
		try
		{
			response.getWriter().write(text);
			response.getWriter().flush();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 输出XML格式Response
	 * 
	 * @param text
	 * @return
	 */
	public ResponseEntity<String> getXMLResponseEntity(String text) {
		return getResponseEntity(text, "application", "xml", "utf-8",
				HttpStatus.OK);
	}
	/**
	 * 输出image格式Response
	 * 
	 * @param text
	 * @return
	 */
	public ResponseEntity<byte[]> getImageResponseEntity(byte[] buffer,
			MediaType mt) {
		HttpHeaders header = new HttpHeaders();
		header.setContentType(mt);
		return new ResponseEntity<byte[]>(buffer, header, HttpStatus.OK);
	}
	/**
	 * 返回json格式Response
	 * @param text
	 * @return
	 */
	public ResponseEntity<String> getJSONResponseEntity(String text) {
		return getResponseEntity(text, "text", "json", "utf-8", HttpStatus.OK);
	}
	/**
	 * 返回String类型Response
	 * @param text
	 * @return
	 */
	public ResponseEntity<String> getTextResponseEntity(String text){
		return getResponseEntity(text, "text", "plain", "utf-8", HttpStatus.OK);
	}

	/**
	 * 根据参数返回ResponseEntity
	 * 
	 * @param text
	 * @param type
	 * @param subtype
	 * @param charset
	 * @param status
	 * @return
	 */
	public ResponseEntity<String> getResponseEntity(String text, String type,
			String subtype, String charset, HttpStatus status) {
		HttpHeaders header = new HttpHeaders();
		MediaType mt = new MediaType(type, subtype, Charset.forName(charset));
		header.setContentType(mt);

		return new ResponseEntity<String>(text, header, status);
	}

	/**
	 * 从对象输出xml
	 * 
	 * @param clazz
	 */
	public String getXMLFromObject(Object object) throws Exception {
		Class<?> clz = object.getClass();
		StringBuffer sb = new StringBuffer();
		if (object != null)
		{
			sb.append("<" + clz.getSimpleName().toLowerCase() + ">");

			Method[] methods = clz.getDeclaredMethods();
			Field[] fields = clz.getDeclaredFields();
			for (Field field : fields)
			{
				String methodName = getMethodName(field.getName());

				if (!isExitMethod(methods, methodName))
				{
					continue;
				}

				Method method = (Method) clz.getMethod(methodName);
				Class<?> returnType = method.getReturnType();
				String typeName = returnType.getSimpleName();				
				if (StringUtils.equalsIgnoreCase(typeName, "ArrayList"))
				{
					ArrayList<?> list = (ArrayList<?>)method.invoke(object);
					if (list!=null && list.size()>0)
					{
						sb.append("<").append(field.getName().toLowerCase()).append(">");
						for(Object c1 : list)
						{
							sb.append(this.getXMLFromObject(c1));
						}
						sb.append("</").append(field.getName().toLowerCase()).append(">");
					}
				}
				else
				{
					String value = String.valueOf(method.invoke(object));
					if (value != null && !value.equals("null"))
					{
						sb.append("<").append(field.getName().toLowerCase())
								.append(">");
						if (StringUtils.equalsIgnoreCase(typeName, "string"))
						{
							sb.append("<![CDATA[").append(value).append("]]>");
						}
						else
						{
							sb.append(value);
						}
						sb.append("</").append(field.getName().toLowerCase())
								.append(">");
					}
				}
			}
			sb.append("</" + clz.getSimpleName().toLowerCase() + ">");
		}
		return sb.toString();
	}
	/**
	 * 获取字段的get方法
	 * @param fieldName
	 * @return
	 * @throws Exception
	 */
	private static String getMethodName(String fieldName) throws Exception {
		return "get" + fieldName.substring(0, 1).toUpperCase()
				+ fieldName.substring(1);
	}

	/**
	 * 判断方法是否存在
	 * 
	 * @param methodName
	 * @return
	 * @throws Exception
	 */
	private static Boolean isExitMethod(Method[] methods, String methodName)
			throws Exception {
		for (Method met : methods)
		{
			if (methodName.equals(met.getName()))
			{
				return true;
			}
		}
		return false;
	}

	/**
	 * 取得当前请求地址
	 */
	public String getRequestUrl() {
		HttpServletRequest request = this.getRequest().get();
		String contextPath = request.getContextPath();
		String url = request.getRequestURI();
		url = url.replaceAll(contextPath + WebSupport.APP_PATH, "");
		return url;
	}

	/**
	 * 获得请求参数
	 */
	public String getParameter(String name) {
		if (getParametersMap().containsKey(name.toLowerCase()))
		{
			String val = getParametersMap().get(name.toLowerCase());
			return StringUtils.isBlank(val) ? "" : (val.indexOf("请输入")>=0||val.equals("undefined")?"":val);
		}
		else
			return null;
	}

	/**
	 * 获得所有的请求参数 比如使用longtu.post('XX?test=test',{a:1,b:2}) 得到的返回字符串就是
	 * text=text&a=1&b=2
	 */
	public String getParameters() {
		HttpServletRequest request = this.getRequest().get();
		Map<String, String[]> paramMap = request.getParameterMap();
		StringBuffer queryString = new StringBuffer("");
		for (String key : paramMap.keySet())
		{
			queryString.append(key).append("=").append(paramMap.get(key)[0])
					.append("&");
		}
		if (queryString.length() > 1)
		{
			queryString.deleteCharAt(queryString.lastIndexOf("&"));
		}
		return queryString.toString();
	}

	/**
	 * 获得parameter table
	 * 
	 */
	public Hashtable<String, String> getParametersMap() {
		HttpServletRequest request = this.getRequest().get();
		Map<String, String[]> paramMap = request.getParameterMap();
		Hashtable<String, String> returnMap = new Hashtable<String, String>();
		for (String key : paramMap.keySet())
		{
			if (!returnMap.containsKey(key.toLowerCase()))
			{
				returnMap.put(key.toLowerCase(), paramMap.get(key)[0]);
			}
		}
		return returnMap;
	}

	/**
	 * 获得完整的请求路径包括所有的请求参数 比如： /main?a=xxx&b=xxx
	 */
	public String getFullRquestPath() {
		String parameters = this.getParameters();
		return this.getRequestUrl()
				+ ("".equals(parameters) ? "" : "?" + parameters);
	}

	/**
	 * 获得请求参数 返回字符串数组
	 */
	public String[] getParameters(String name) {
		HttpServletRequest request = this.getRequest().get();
		return request.getParameterValues(name);
	}

	/**
	 * 获得request attribute
	 */
	public Object getAttribute(String name) {
		HttpServletRequest request = this.getRequest().get();
		return request.getAttribute(name);
	}

	/**
	 * 设置request attribute
	 */
	public void setAttribute(String name, Object obj) {
		HttpServletRequest request = this.getRequest().get();
		request.setAttribute(name, obj);
	}

	/**
	 * 得到用户的ip地址
	 * 
	 * @return
	 */
	public String getIpAddr() {
		HttpServletRequest request = this.getRequest().get();
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
		{
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
		{
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
		{
			ip = request.getRemoteAddr();
		}
		return ip;
	}

	/**
	 * 添加cookie
	 * 
	 * @param response
	 * @param name
	 *            cookie的名称
	 * @param value
	 *            cookie的值
	 * @param maxAge
	 *            cookie存放的时间(以秒为单位,假如存放三天,即3*24*60*60; 如果值为0,cookie将随浏览器关闭而清除)
	 */
	public void addCookie(String name, String value, int maxAge) {
		HttpServletResponse response = this.getResponse().get();
		Cookie cookie = new Cookie(name, value);
		cookie.setPath("/");
		if (maxAge > 0)
			cookie.setMaxAge(maxAge);
		response.addCookie(cookie);
	}

	/**
	 * 获取cookie的值
	 * 
	 * @param request
	 * @param name
	 *            cookie的名称
	 * @return
	 */
	public String getCookieByName(String name) {
		HttpServletRequest request = this.getRequest().get();
		Map<String, Cookie> cookieMap = readCookieMap(request);
		if (cookieMap.containsKey(name))
		{
			Cookie cookie = (Cookie) cookieMap.get(name);
			return cookie.getValue();
		}
		else
		{
			return null;
		}
	}

	protected Map<String, Cookie> readCookieMap(HttpServletRequest request) {
		Map<String, Cookie> cookieMap = new HashMap<String, Cookie>();
		Cookie[] cookies = request.getCookies();
		if (null != cookies)
		{
			for (int i = 0; i < cookies.length; i++)
			{
				cookieMap.put(cookies[i].getName(), cookies[i]);
			}
		}
		return cookieMap;
	}

	/**
	 * 得到web根目录
	 * 
	 * @return
	 */
	public String getAppBasePath() {
		HttpServletRequest request = this.getRequest().get();
		HttpSession session = request.getSession(true);
		return session.getServletContext().getRealPath("");
	}
	
	public void removeSession(String key){
		HttpSession session = this.getRequest().get().getSession();
		session.removeAttribute(key);
		session.invalidate();
	}

	public ThreadLocal<HttpServletRequest> getRequest() {
		return request;
	}

	public void setRequest(ThreadLocal<HttpServletRequest> request) {
		this.request = request;
	}

	public ThreadLocal<HttpServletResponse> getResponse() {
		return response;
	}

	public void setResponse(ThreadLocal<HttpServletResponse> response) {
		this.response = response;
	}

	public String getPathInfo() {
		HttpServletRequest request = this.getRequest().get();
		return request.getPathInfo();
	}
	
	public String getLogInfo()
	{
		HttpServletRequest request = this.getRequest().get();
		StringBuilder sb = new StringBuilder();
		sb.append(request.getRemoteAddr()).append("\t");
		sb.append(request.getQueryString());
		return sb.toString();
	}
}
